package boboLang;

import java.io.IOException;
import java.util.Arrays;

/*
* 抽象类
* 只具有包访问权限，为了让BoboStringBuffer和BoboStringBuilder继承
* */
abstract class BoboAbstractStringBuilder implements Appendable,CharSequence {

    /*
    * 存储字符串，包访问权限，被子类继承
    * */
    char[] value;

    /*
    * 字符串计数
    * */
    int count;


    /*
    * 构造函数
    * */
    BoboAbstractStringBuilder(){}
    BoboAbstractStringBuilder(int capacity){
        value = new char[capacity];
    }

    /*
    * append函数
    *
    * */
    public BoboAbstractStringBuilder append(BoboString boboString){
        if (boboString == null){
            return appendNull();
        }
        int len = boboString.length();
        ensureCapacityInternal(count + len);
        boboString.getChars(0, len, value, count);
        count += len;
        return this;
    }

    private BoboAbstractStringBuilder appendNull(){
        int c = count;
        ensureCapacityInternal(c + 4);
        final char[] value = this.value;
        value[c++] = 'n';
        value[c++] = 'u';
        value[c++] = 'l';
        value[c++] = 'l';
        count = c;
        return this;
    }
    /*
    * 扩容操作：比较耗时，最好提前指定需要用到的容量
    * */
    public void ensureCapacity(int minimumCapacity){
        if (minimumCapacity > 0){
            ensureCapacityInternal(minimumCapacity);
        }
    }

    private void ensureCapacityInternal(int minimumCapacity){
        if (minimumCapacity - value.length > 0 ){
            Arrays.copyOf(value,newCapacity(minimumCapacity) );
        }
    }

    /*
    * 数组最大长度，这是虚拟机的限制，
    * 因为一些虚拟机会保留数组头部的几个字节
    * 尝试申请更大的数组可能会造成：OutOfMemoryError
    * */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    private int newCapacity(int minCapacity){
        int newCapacity = (value.length << 1) + 2;
        if (newCapacity - minCapacity < 0){
            newCapacity = minCapacity;
        }
        if (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0){
            //newCapacity必然已经超出范围，所以尝试是否minCapacity是否超出整数范围
            return hugeCapacity(minCapacity);
        } else {
            return newCapacity;
        }
    }

    private int hugeCapacity(int minCapacity){
        if (Integer.MAX_VALUE - minCapacity < 0){
            throw new OutOfMemoryError();
        }
        return (minCapacity > MAX_ARRAY_SIZE) ? minCapacity : MAX_ARRAY_SIZE;
    }


    /*需要子类重写toString方法*/
    @Override
    public abstract String toString();

    @Override
    public Appendable append(CharSequence csq) throws IOException {
        return null;
    }

    @Override
    public Appendable append(CharSequence csq, int start, int end) throws IOException {
        return null;
    }

    @Override
    public Appendable append(char c) throws IOException {
        return null;
    }

    @Override
    public int length() {
        return count;
    }

    @Override
    public char charAt(int index) {
        if (index < 0 || index >= count){
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index];
    }

    @Override
    public CharSequence subSequence(int start, int end) {
        return null;
    }
}
